package code_analysis

import (
	"fmt"
	"gitee.com/huanminabc/go-utils/common"
	"gitee.com/huanminabc/go-utils/file"
	"strings"
)

type TokenType string

//=================================================下面是识别token的类型===================================================

const (
	//标识符,  变量和关键字
	IDENTIFIER TokenType = "IDENTIFIER" //标识符:变量名,函数名,类型名 各种关键字
	//运算符
	OPERATOR TokenType = "OPERATOR" //运算符:+,-,*,/,%,++,--,==,!=,>,<,>=,<=,&&,||,!,+=,-=,*=,/=,%=,^=,|, &
	//代码常用符号
	SYMBOL TokenType = "SYMBOL" //符号:  .  ( ) [ ] { }  : ; ,  ... @   ?
	//常亮,意思就是不会变化的值
	CONSTANT TokenType = "CONSTANT" //常量:数字,字符串,字符, 字符串模板 ,布尔值,空值
	//注释
	COMMENT TokenType = "COMMENT" //注释:单行注释,多行注释
)

// 值类型 ,只有常量才有值类型
type ValueType string

const (
	//无
	NONE ValueType = "NONE"
	//整数
	INT ValueType = "INT"
	//浮点数
	FLOAT ValueType = "FLOAT"
	//字符串
	STRING ValueType = "STRING"
	//字符
	CHAR ValueType = "CHAR"
	//字符串模板
	STRING_TEMPLATE ValueType = "STRING_TEMPLATE"

	//布尔 true  false
	BOOL ValueType = "BOOL"
	//空值  null
	NULL ValueType = "NULL"

	//数组索引 a[1]
	ARRAY_INDEX ValueType = "ARRAY_INDEX"
)

// 判断字符串是什么类型的
func IsDataType(str string) ValueType {
	//判断是否是数字
	if common.IsInt(str) {
		return INT
	}
	if common.IsFloat(str) {
		return FLOAT
	}
	//判断
	if str == "true" || str == "false" {
		return BOOL
	}
	if str == "null" {
		return NULL
	}
	//判断是否是字符串
	if strings.HasPrefix(str, "\"") && strings.HasSuffix(str, "\"") {
		return STRING
	}
	//判断是否是字符
	if strings.HasPrefix(str, "'") && strings.HasSuffix(str, "'") {
		return CHAR
	}
	//判断是否是字符串模板
	if strings.HasPrefix(str, "`") && strings.HasSuffix(str, "`") {
		return STRING_TEMPLATE
	}
	return NONE

}

type Token struct {
	//token类型
	Type TokenType
	//值
	Value string
	//值类型
	ValueType ValueType

	//行号 			,从0开始
	Line int
	//行结束位置 ,一般是不用的,只有在注释等多行为一体的时候才有用, 并且不用管列号
	LineEnd int
	//列号,开始位置   ,从0开始
	ColumnStart int
	//列号,结束位置   ,从0开始
	ColumnEnd int

	//=================================================下面是二次处理的扩展属性===================================================

	//是否是关键字 ,由调用方二次处理自行判断TokenType是否是IDENTIFIER ,如果是那么就判断是否是关键字
	IsKeyword bool
	// 标记  在go中是`xxx:""`  在java是@xxx 在Python是@xxx
	// 这个也是由调用方二次处理解析出来的
	Tag bool
	//包路径 , 不同的语言有不同的包路径,这个是由调用方二次处理解析出来的
	Import bool
	//文件作用域,不同的语言有不同的作用域,这个是由调用方二次处理解析出来的
	Package bool
}

// 打印
func (t Token) String() string {
	return fmt.Sprintf("类型:%s,值:%s,值类型:%s,开始行:%d, 结束行:%d, 开始列:%d, 结束列:%d, 是否是关键字:%t, 标记:%t ,包路径:%t ,文件作用域:%t",
		t.Type, t.Value, t.ValueType, t.Line, t.LineEnd, t.ColumnStart, t.ColumnEnd, t.IsKeyword, t.Tag, t.Import, t.Package)
}

func NewToken(type_ TokenType, value string, valueType ValueType, line int, columnStart int, columnEnd int) Token {
	return Token{
		Type:        type_,
		Value:       value,
		ValueType:   valueType,
		Line:        line,
		ColumnStart: columnStart,
		ColumnEnd:   columnEnd,
	}
}

func NewTokenLine(type_ TokenType, value string, valueType ValueType, line int, lineEnd int) Token {
	return Token{
		Type:        type_,
		Value:       value,
		ValueType:   valueType,
		Line:        line,
		LineEnd:     lineEnd,
		ColumnStart: 0,
		ColumnEnd:   0,
	}
}

//统计到多少行有多少字符

// 解析代码转换为tokens数组
func FileToTokens(filePath string) []Token {
	codeLines := file.ReadFile(filePath)     //读取文件
	codeRunes := replaceLineBreak(codeLines) //替换换行符
	tokens := analysisToken(codeRunes)       //解析代码
	CheckAllBracket(tokens)                  //检查括号是否成对
	return tokens
}

// 将字符串转换为tokens
func CodeToTokens(codes string) []Token {
	codeRunes := replaceLineBreak(codes) //替换换行符
	tokens := analysisToken(codeRunes)   //解析代码
	CheckAllBracket(tokens)              //检查括号是否成对
	return tokens
}

func analysisToken(codeLines []rune) []Token {
	//存储所有的token
	var tokens []Token
	var rowIndex = 1
	var _col_ = 1
	//扫描每个字母
	_Len_ := len(codeLines)

	for i := 0; i < _Len_; i++ {
		//跳过空格
		if codeLines[i] == ' ' {
			_col_++
			continue
		}
		//遇到;跳过然后+1
		if codeLines[i] == '\n' {
			//判断上一个是否是;如果是,则不添加
			if len(tokens) > 0 && tokens[len(tokens)-1].Value != ";" {
				//添加一个结束符号
				tokens = append(tokens, NewToken(SYMBOL, ";", NONE, rowIndex, _col_, _col_+1))
			}
			rowIndex++
			_col_ = 1
			continue
		}
		lenTokens := len(tokens)
		tokenType := getTokenType(&rowIndex, &i, codeLines, &_col_, &tokens, lenTokens)
		tokens = append(tokens, tokenType)
		tokens = GetTokenTwiceHandle(tokenType, tokens)
	}
	return tokens
}

// 根据输入的字符串,返回对应的token类型
func getTokenType(row, col *int, codeLines []rune, _col_ *int, tokens *[]Token, lenTokens int) Token {

	//判断是否是注释
	if codeLines[*col] == '/' && codeLines[*col+1] == '/' {
		//单行注释
		*col += 2
		var startCol = *col
		var endCol = *_col_
		for ; *col < len(codeLines); *col++ {
			if codeLines[*col] == '\n' {
				//*col++   让外部循环的col指向下一个字符
				value := string(codeLines[startCol:*col])
				//去空
				value = strings.TrimSpace(value)
				*col--
				token := NewToken(COMMENT, value, NONE, *row, *_col_, endCol+2)
				*_col_ = endCol + 2
				return token
			}
			endCol++
		}
	}
	//判断是否是/*注释
	if codeLines[*col] == '/' && codeLines[*col+1] == '*' {
		//多行注释
		*col += 2
		var startCol = *col
		var startLine = *row
		for ; *col < len(codeLines); *col++ {
			//遇到换行符就+1
			if codeLines[*col] == '\n' {
				*row++
			}
			if codeLines[*col] == '*' && codeLines[*col+1] == '/' {
				value := string(codeLines[startCol : *col+1])
				//去掉每行开头的空格和*
				var newValue strings.Builder
				for _, v := range strings.Split(value, "\n") {
					v = strings.TrimSpace(v)
					v = strings.TrimLeft(v, " *")
					newValue.WriteString(v + "\n")
				}
				s := newValue.String()
				s = strings.TrimSpace(s)
				token := NewTokenLine(COMMENT, s, NONE, startLine, *row)
				*col += 2
				*row++
				*_col_ = 1
				return token
			}

		}
	}
	//判断是否是字符
	if codeLines[*col] == '"' {
		//字符串
		var temp []rune
		var symbolCount = 0
		for *col++; *col < len(codeLines); *col++ {
			//如果遇到转移\"那么就跳过
			if codeLines[*col] == '\\' && *col+1 < len(codeLines) && codeLines[*col+1] == '"' {
				temp = append(temp, codeLines[*col+1])
				*col++
				symbolCount++
				continue
			}

			if codeLines[*col] == '"' {
				token := NewToken(CONSTANT, "\""+string(temp)+"\"", STRING, *row, *_col_, *_col_+len(temp)+2+symbolCount)
				*_col_ += len(temp) + 2 + symbolCount
				return token
			}
			temp = append(temp, codeLines[*col])
		}
	}
	//判断是否是字符
	if codeLines[*col] == '\'' {

		//字符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '\\' {
			*col++
			*_col_++
		}
		*col++ //跳过字符
		if *col < len(codeLines) && codeLines[*col] == '\'' {
			var valueRune = string(codeLines[*col-1])
			//判断不是空字符
			if valueRune == "'" {
				valueRune = ""
			}
			valueRune = "'" + valueRune + "'"
			token := NewToken(CONSTANT, valueRune, CHAR, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}

		panic(fmt.Sprintf("第%d行,第%d列,字符格式错误", *row, *_col_))
	}
	//判断是否是字符串模板``
	if codeLines[*col] == '`' {
		//字符串模板
		var temp []rune
		var newlineCount = 0
		for *col++; *col < len(codeLines); *col++ {
			//遇到\n
			if codeLines[*col] == '\n' {
				newlineCount++
				*row++
				*_col_ = 1
			}
			if codeLines[*col] == '`' {
				var value = "`" + string(temp) + "`"
				token := NewToken(CONSTANT, value, STRING_TEMPLATE, *row, *_col_, *_col_+len(temp)+2-newlineCount)
				*_col_ += len(temp) + 2 - newlineCount
				return token

			}
			temp = append(temp, codeLines[*col])
		}
	}

	//判断是否是标识符 ,必须在关键字之后
	if (codeLines[*col] >= 'a' && codeLines[*col] <= 'z') || (codeLines[*col] >= 'A' && codeLines[*col] <= 'Z') {
		//标识符
		var temp []rune
		for ; *col < len(codeLines); *col++ {
			if (codeLines[*col] >= 'a' && codeLines[*col] <= 'z') || (codeLines[*col] >= 'A' && codeLines[*col] <= 'Z') || (codeLines[*col] >= '0' && codeLines[*col] <= '9' || codeLines[*col] == '_') {
				temp = append(temp, codeLines[*col])
			} else {
				*col--
				break
			}
		}
		//判断是否是布尔
		if string(temp) == "true" || string(temp) == "false" {
			token := NewToken(CONSTANT, string(temp), BOOL, *row, *_col_, *_col_+len(temp))
			*_col_ += len(temp)
			return token
		}
		//判断是否是null
		if string(temp) == "null" {
			token := NewToken(CONSTANT, string(temp), NULL, *row, *_col_, *_col_+len(temp))
			*_col_ += len(temp)
			return token
		}

		token := NewToken(IDENTIFIER, string(temp), NONE, *row, *_col_, *_col_+len(temp))
		*_col_ += len(temp)
		return token
	}

	//判断是否是运算符
	if codeLines[*col] == '+' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '+' {
			token := NewToken(OPERATOR, "++", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		//+=
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, "+=", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}

		*_col_++
		*col--
		token := NewToken(OPERATOR, "+", NONE, *row, *_col_-1, *_col_)
		return token

	}

	if codeLines[*col] == '-' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '-' {
			token := NewToken(OPERATOR, "--", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		//-=
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, "-=", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--
		return NewToken(OPERATOR, "-", NONE, *row, *_col_-1, *_col_)
	}

	if codeLines[*col] == '*' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, "*=", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*col--
		*_col_++
		token := NewToken(OPERATOR, "*", NONE, *row, *_col_-1, *_col_)
		return token
	}

	if codeLines[*col] == '/' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, "/=", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--
		token := NewToken(OPERATOR, "/", NONE, *row, *_col_-1, *_col_)
		return token
	}

	if codeLines[*col] == '%' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, "%=", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--
		token := NewToken(OPERATOR, "%", NONE, *row, *_col_-1, *_col_)
		return token
	}

	//判断是^
	if codeLines[*col] == '^' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, "^=", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--
		token := NewToken(OPERATOR, "^", NONE, *row, *_col_-1, *_col_)
		return token
	}

	if codeLines[*col] == '!' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, "!=", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--
		token := NewToken(OPERATOR, "!", NONE, *row, *_col_-1, *_col_)
		return token
	}

	//判断是否是运算符
	if codeLines[*col] == '=' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, "==", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--
		token := NewToken(OPERATOR, "=", NONE, *row, *_col_-1, *_col_)
		return token

	}
	if codeLines[*col] == '>' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, ">=", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--
		return NewToken(OPERATOR, ">", NONE, *row, *_col_-1, *_col_)
	}
	if codeLines[*col] == '<' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '=' {
			token := NewToken(OPERATOR, "<=", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--

		return NewToken(OPERATOR, "<", NONE, *row, *_col_-1, *_col_)

	}

	if codeLines[*col] == '&' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '&' {
			token := NewToken(OPERATOR, "&&", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--
		return NewToken(OPERATOR, "&", NONE, *row, *_col_-1, *_col_)
	}

	if codeLines[*col] == '|' {
		//运算符
		*col++
		if *col < len(codeLines) && codeLines[*col] == '|' {
			token := NewToken(OPERATOR, "||", NONE, *row, *_col_, *_col_+2)
			*_col_ += 2
			return token
		}
		*_col_++
		*col--
		return NewToken(OPERATOR, "|", NONE, *row, *_col_-1, *_col_)
	}

	//.   ...
	if codeLines[*col] == '.' {
		//判断是3个点还是一个点
		if *col+2 < len(codeLines) && codeLines[*col+1] == '.' && codeLines[*col+2] == '.' {
			token := NewToken(SYMBOL, "...", NONE, *row, *_col_, *_col_+3)
			*col += 2
			*_col_ += 3
			return token
		}

		token := NewToken(SYMBOL, ".", NONE, *row, *_col_, *_col_+1)
		*_col_++
		return token
	}

	//判断是否是数字
	if (codeLines[*col] >= '0' && codeLines[*col] <= '9') || codeLines[*col] == '.' {
		//常量
		var temp []rune
		for ; *col < len(codeLines); *col++ {
			if (codeLines[*col] >= '0' && codeLines[*col] <= '9') || codeLines[*col] == '.' {
				temp = append(temp, codeLines[*col])
			} else {
				*col--
				break
			}
		}
		//判断是否是整数
		if strings.Index(string(temp), ".") == -1 {
			token := NewToken(CONSTANT, string(temp), INT, *row, *_col_, *_col_+len(temp))
			*_col_ += len(temp)
			return token
		}

		token := NewToken(CONSTANT, string(temp), FLOAT, *row, *_col_, *_col_+len(temp))
		*_col_ += len(temp)
		return token
	}
	//判断是否是分隔符
	if codeLines[*col] == ':' || codeLines[*col] == '(' || codeLines[*col] == ')' || codeLines[*col] == '[' ||
		codeLines[*col] == ']' || codeLines[*col] == '{' || codeLines[*col] == '}' || codeLines[*col] == ',' ||
		codeLines[*col] == ';' || codeLines[*col] == '@' || codeLines[*col] == '?' {
		//判断如果是]的话,并且前面是INT,在前面是[的话,那么就是数组索引 str[12]

		if codeLines[*col] == ']' && (*tokens)[lenTokens-1].Type == CONSTANT && (*tokens)[lenTokens-1].ValueType == INT &&
			(*tokens)[lenTokens-2].Value == "[" && (*tokens)[lenTokens-3].Type == IDENTIFIER {
			//把这几个合并为一个 token
			//取出
			var identifier = (*tokens)[lenTokens-3]
			var index = (*tokens)[lenTokens-1]
			//删除前面的
			*tokens = (*tokens)[:lenTokens-3]
			//添加一个新的
			token := NewToken(IDENTIFIER, identifier.Value+"["+index.Value+"]", ARRAY_INDEX, identifier.Line, identifier.ColumnStart, index.ColumnEnd)
			*_col_++
			return token
		}

		token := NewToken(SYMBOL, string(codeLines[*col]), NONE, *row, *_col_, *_col_+1)
		*_col_++
		return token
	}

	panic(fmt.Sprintf("第%d行,第%d列,值:%s,无法识别的字符,可能是不兼容", *row, *_col_, string(codeLines[*col])))
}

//===========================================辅助函数===========================================

// 检查所有的括号是否成对出现,(,),{,},[,] ,如果不成对则抛出异常,并返回错误信息
func CheckAllBracket(tokens []Token) {
	var stack []Token
	for i := 0; i < len(tokens); i++ {
		if tokens[i].Value == "(" || tokens[i].Value == "{" || tokens[i].Value == "[" {
			stack = append(stack, tokens[i])
		} else if tokens[i].Value == ")" || tokens[i].Value == "}" || tokens[i].Value == "]" {
			if len(stack) == 0 {
				panic(fmt.Sprintf("第%d行,第%d列,括号不成对", tokens[i].Line, tokens[i].ColumnStart))
			}
			if tokens[i].Value == ")" && stack[len(stack)-1].Value != "(" {
				panic(fmt.Sprintf("第%d行,第%d列,括号不成对", tokens[i].Line, tokens[i].ColumnStart))
			}
			if tokens[i].Value == "}" && stack[len(stack)-1].Value != "{" {
				panic(fmt.Sprintf("第%d行,第%d列,括号不成对", tokens[i].Line, tokens[i].ColumnStart))
			}
			if tokens[i].Value == "]" && stack[len(stack)-1].Value != "[" {
				panic(fmt.Sprintf("第%d行,第%d列,括号不成对", tokens[i].Line, tokens[i].ColumnStart))
			}
			stack = stack[:len(stack)-1]
		}
	}
	if len(stack) != 0 {
		panic(fmt.Sprintf("第%d行,第%d列,括号不成对", stack[len(stack)-1].Line, stack[len(stack)-1].ColumnStart))
	}
}

// 二次加工Token ,把 ++ --    += -=    *= /=    %= 这些展开 或者合并
// 合并  ++   需要将前一个token的值合并  token  ++ => token + 1
// 展开  +=   需要将前一个token的值展开  token = token + token    var a+=1*3  =>  var a = a + 1*3
func GetTokenTwiceHandle(token Token, tokens []Token) []Token {

	//判断是否是OPERATOR 并且是 ++ 或者 --
	if token.Type == OPERATOR && (token.Value == "++" || token.Value == "--") {
		//找到前一个token
		var preToken = tokens[len(tokens)-2]
		//判断前一个token是否是标识符
		if preToken.Type != IDENTIFIER {
			panic(fmt.Sprintf("第%d行,第%d列,++或者--前面必需是标识符", token.Line, token.ColumnStart))
		}
		//判断是++还是--
		if token.Value == "++" {
			//将++替换为+1

			//1.删除当++这个token
			tokens = tokens[:len(tokens)-1]
			//2.添加+ token
			tokens = append(tokens, NewToken(OPERATOR, "+", NONE, token.Line, token.ColumnStart, token.ColumnStart+1))
			//3.添加1 token
			tokens = append(tokens, NewToken(CONSTANT, "1", INT, token.Line, token.ColumnStart+1, token.ColumnStart+2))

		} else {
			//将--替换为-1
			//1.删除当--这个token
			tokens = tokens[:len(tokens)-1]
			//2.添加- token
			tokens = append(tokens, NewToken(OPERATOR, "-", NONE, token.Line, token.ColumnStart, token.ColumnStart+1))
			//3.添加1 token
			tokens = append(tokens, NewToken(CONSTANT, "1", INT, token.Line, token.ColumnStart+1, token.ColumnStart+2))

		}
		return tokens
	}
	//判断是否是OPERATOR 并且是 += -= *= /= %=
	if token.Type == OPERATOR && (token.Value == "+=" || token.Value == "-=" || token.Value == "*=" || token.Value == "/=" || token.Value == "%=") {
		//找到前一个token
		var preToken = tokens[len(tokens)-2]
		//判断前一个token是否是标识符
		if preToken.Type != IDENTIFIER {
			panic(fmt.Sprintf("第%d行,第%d列,+= -= *= /= %%=前面必需是标识符", token.Line, token.ColumnStart))
		}
		//判断是+=还是-=
		if token.Value == "+=" {
			//将+=替换为+ token
			//1.删除当+=这个token
			tokens = tokens[:len(tokens)-1]
			//2.添加=
			tokens = append(tokens, NewToken(OPERATOR, "=", NONE, token.Line, token.ColumnStart+1, token.ColumnStart+2))
			//3.添加token
			tokens = append(tokens, NewToken(IDENTIFIER, preToken.Value, preToken.ValueType, token.Line, preToken.ColumnStart, preToken.ColumnEnd))
			//4.添加+
			tokens = append(tokens, NewToken(OPERATOR, "+", NONE, token.Line, token.ColumnStart, token.ColumnStart+1))
			return tokens
		}
		if token.Value == "-=" {
			//将-=替换为- token
			//1.删除当-=这个token
			tokens = tokens[:len(tokens)-1]
			//2.添加=
			tokens = append(tokens, NewToken(OPERATOR, "=", NONE, token.Line, token.ColumnStart+1, token.ColumnStart+2))
			//3.添加token
			tokens = append(tokens, NewToken(IDENTIFIER, preToken.Value, preToken.ValueType, token.Line, preToken.ColumnStart, preToken.ColumnEnd))
			//4.添加-
			tokens = append(tokens, NewToken(OPERATOR, "-", NONE, token.Line, token.ColumnStart, token.ColumnStart+1))
			return tokens
		}
		if token.Value == "*=" {
			//将*=替换为* token
			//1.删除当*=这个token
			tokens = tokens[:len(tokens)-1]
			//2.添加=
			tokens = append(tokens, NewToken(OPERATOR, "=", NONE, token.Line, token.ColumnStart+1, token.ColumnStart+2))
			//3.添加token
			tokens = append(tokens, NewToken(IDENTIFIER, preToken.Value, preToken.ValueType, token.Line, preToken.ColumnStart, preToken.ColumnEnd))
			//4.添加*
			tokens = append(tokens, NewToken(OPERATOR, "*", NONE, token.Line, token.ColumnStart, token.ColumnStart+1))
			return tokens
		}
		if token.Value == "/=" {
			//将/=替换为/ token
			//1.删除当/=这个token
			tokens = tokens[:len(tokens)-1]
			//2.添加=
			tokens = append(tokens, NewToken(OPERATOR, "=", NONE, token.Line, token.ColumnStart+1, token.ColumnStart+2))
			//3.添加token
			tokens = append(tokens, NewToken(IDENTIFIER, preToken.Value, preToken.ValueType, token.Line, preToken.ColumnStart, preToken.ColumnEnd))
			//4.添加/
			tokens = append(tokens, NewToken(OPERATOR, "/", NONE, token.Line, token.ColumnStart, token.ColumnStart+1))
			return tokens
		}
		if token.Value == "%=" {
			//将%=替换为% token
			//1.删除当%=这个token
			tokens = tokens[:len(tokens)-1]
			//2.添加=
			tokens = append(tokens, NewToken(OPERATOR, "=", NONE, token.Line, token.ColumnStart+1, token.ColumnStart+2))
			//3.添加token
			tokens = append(tokens, NewToken(IDENTIFIER, preToken.Value, preToken.ValueType, token.Line, preToken.ColumnStart, preToken.ColumnEnd))
			//4.添加%
			tokens = append(tokens, NewToken(OPERATOR, "%", NONE, token.Line, token.ColumnStart, token.ColumnStart+1))
			return tokens
		}

	}

	return tokens

}

// 把所有的\r\n,\r,\n替换为\n
func replaceLineBreak(codeLines string) []rune {
	var temp strings.Builder
	for i := 0; i < len(codeLines); i++ {
		if codeLines[i] == '\t' { //替换制表符为4个空格
			temp.WriteByte(' ')
			temp.WriteByte(' ')
			temp.WriteByte(' ')
			temp.WriteByte(' ')
			continue
		}
		if codeLines[i] == '\r' {
			if i+1 < len(codeLines) && codeLines[i+1] == '\n' {
				i++
			}
			temp.WriteByte('\n')
		} else {
			temp.WriteByte(codeLines[i])
		}
	}
	//判断最后一个字符是否是\n,如果不是,那么就加上,避免无法识别结尾
	if temp.String()[temp.Len()-1] != '\n' {
		temp.WriteByte('\n')
	}
	return []rune(temp.String())
}
